在 Swift 中用泛型用得很爽了, 回过头来有时候还是想要在 OC 中也用到这项技术。对 iOS 开发来说可能很多人都觉得 OC 是没有泛型的,但其实早在15年,苹果就在 OC 中引入了泛型。虽说引入泛型的目的是更好的实现 Swift 和 OC 的兼容(苹果叫它Lightweight generics
)。
很多人都写过这样的代码:
|
|
这行代码在某个类中声明了一个叫做 dataSource
的数组属性。加上 <Model *>
限制了这个数组当中的 element 必须是 Model
的对象。 在之后的代码中 self.dataSource[0]
就直接是一个 Model
对象了 这就是 OC 中最常用的范型写法。对应的 Swift 代码应该是这样的:
|
|
现在来想想这种场景。水果店、肉店、蔬菜店…. 这种情况:
|
|
这段代码声明了一个泛型类 Mall
这个类有库存stock
也有采购(buy
)销售(sell
)两个方法。在使用这个类的时候,我们可以先声明几个代表各类商品的协议或者枚举:
|
|
然后在通过传入对应的类型,枚举,协议来初始化这个商店泛型类:
|
|
使用范型让我们规避了需要声明:FruitMall
MeatsMall
等等之类的对象,然后在每个对象里面写几乎同样的代码。可能你这时候想到了使用继承或者协议,但是即使这么做确实减少了不少代码量,但是维护各种类很蛋疼啊。
同样的功能在 OC 中要怎么实现呢?
.h
|
|
.m
|
|
这段代码实现了上面同样的功能。在使用上:
还是需要有对应的协议或者类,但是枚举貌似是不可以的。
|
|
甚至我们还可以给 Mall 添加一个 Extension(对应 OC 是 category):
|
|
在 OC 中还有一点需要注意的是类型转换。假如有两个类,一个是另外一个的子类。如下,有饮料商店,还有一个矿泉水商店。其中 Drinks
是 Water
的父类。
|
|
如果这样之间转换的话,编译器会抛出一个警告⚠️。如果想要将一个包含子类的范型类对象转换成一个包含父类的范型类对象,需要使用到 __covariant 这个关键字。我们再来看看 .h 文件。
|
|
相反的,还有 __contravariant 这个关键字, 允许将包含父类的范型对象转换成包含子类的范型对象。唯一的问题是: 两个关键字不能同时存在。